Skip to content

Add LLM-generated questions to create-quiz + backfill media-recording README#85

Merged
sgeinitz merged 4 commits into
mainfrom
create-quiz-llm-generation
May 6, 2026
Merged

Add LLM-generated questions to create-quiz + backfill media-recording README#85
sgeinitz merged 4 commits into
mainfrom
create-quiz-llm-generation

Conversation

@sgeinitz

@sgeinitz sgeinitz commented May 6, 2026

Copy link
Copy Markdown
Owner

Summary

  • create-quiz LLM generation. Per question, the instructor now picks [p]laceholder, [g]enerate w/ LLM, or [e]nd quiz. The g path sends a natural-language seed (e.g. "a question on Big-O for binary search") to the cloud text model (default gemini-3-flash-preview, requires OLLAMA_API_KEY) and returns a Canvas-shaped question of one of seven auto-gradable types: multiple_choice_question, multiple_answers_question, true_false_question, fill_in_multiple_blanks_question, multiple_dropdowns_question, matching_question, calculated_question. The proposed question is previewed (with * marking correct answers, plus per-type extras like match pairs / formula variables) and the instructor accepts/regenerates/skips before it's pushed to Canvas. points_possible is forced to 1; the instructor refines wording and points later in the Canvas UI. The canvigator_llm module is lazy-imported only on the first g, so pure-placeholder runs still work without OLLAMA_API_KEY set.
  • README backfill for media-recording tasks (Media recording check-ins: create, transcribe, grade, and analyze #84 shipped them but never documented them in the README). Adds sections for create-media-recording-assignment, get-media-recordings, analyze-media-recordings; updates the available-tasks list, the --dry-run flag note, and adds an --auto-grade example.

New pure helpers in canvigator_llm.py: _build_quiz_question_prompt, _parse_quiz_question (markdown-fence-tolerant JSON parse, strips points_possible, rejects unknown types), and the cloud-bound generate_quiz_question(user_seed). New helper in canvigator_course.py: _reviewGeneratedQuestion for the [y]/[r]/[s] accept/regenerate/skip flow.

Test plan

  • python -m pytest test_canvigator.py — 230/230 passing (9 new tests for the quiz-question helpers).
  • flake8 (both passes from CLAUDE.md) — clean.
  • Live smoke test against a Canvas sandbox with OLLAMA_API_KEY set:
    • [p] → typed description → placeholder created (today's behavior).
    • [g] → seed for a multiple-choice question → preview shows 4 answers with one starred → y accepts.
    • [g] → seed for a true/false question → type comes back as true_false_question.
    • [g]r regenerates with the same seed.
    • [g]s skips and doesn't write.
    • [e] (and Enter) → ends the quiz with whatever's been added.
    • With OLLAMA_API_KEY unset, a pure-placeholder run still works (no lazy-import triggered).
    • With OLLAMA_API_KEY set but OLLAMA_TEXT_MODEL pointing at a bogus model, g fails gracefully and re-prompts.
  • Spot-check the new README sections render correctly on GitHub.

🤖 Generated with Claude Code

sgeinitz and others added 2 commits May 3, 2026 15:59
Per question, the instructor now picks [p]laceholder, [g]enerate w/ LLM,
or [e]nd quiz. The 'g' path sends a natural-language seed to the cloud
text model (default gemini-3-flash-preview) and returns a Canvas-shaped
question of one of seven auto-gradable types (multiple_choice,
multiple_answers, true_false, fill_in_multiple_blanks,
multiple_dropdowns, matching, calculated). The proposed question is
previewed and the instructor accepts/regenerates/skips before it lands
on Canvas. points_possible is forced to 1; the instructor refines the
rest in the Canvas UI.

The canvigator_llm module is lazy-imported only on the first 'g', so
pure-placeholder runs still work without OLLAMA_API_KEY set.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds README sections for create-media-recording-assignment,
get-media-recordings, and analyze-media-recordings (the workflow shipped
in #84 but never documented in the README). Also updates the
available-tasks list, the --dry-run task list, and adds an --auto-grade
example. Backfills coverage that was previously only in CLAUDE.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7b97577196

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread canvigator_llm.py Outdated
sgeinitz and others added 2 commits May 5, 2026 19:52
The "scale": 0" had a stray trailing quote, making the JSON template
shown to the LLM syntactically invalid. Weaker models can mirror the
malformed pattern, which then fails _parse_quiz_question and the
generation gets skipped instead of producing a usable draft.

Caught in PR review.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previously [r]egenerate called the model with the same seed prompt and
temperature=0.4, so successive drafts often looked nearly identical.

Now _reviewGeneratedQuestion accumulates each rejected draft and passes
the list to generate_quiz_question, which:

  - appends a "REJECTED draft(s); produce a SUBSTANTIVELY DIFFERENT
    new draft" instruction to the user prompt with a compact summary
    of each prior draft (type, question text, marked answers / match
    pairs / variables-formulas), and
  - bumps temperature 0.4 -> 0.8 when prior_drafts is non-empty, so
    the sampler has room to actually diverge.

The first generation behavior is unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@sgeinitz sgeinitz merged commit da149e3 into main May 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant